
#include <iostream>
#include <map>
#include <vector>


#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/Socket.h"
#include "Poco/Observer.h"
#include "Poco/NObserver.h"
#include "Poco/Exception.h"
#include "Poco/Thread.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Runnable.h"
#include "Poco/AutoPtr.h"
#include "Poco/Mutex.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/RefCountedObject.h"


#include "socketlist.h"
#include "Reactor.h"
#include "iothread.h"
#include "sockethandler.h"


using Poco::Net::ReadableNotification;
using Poco::Net::ShutdownNotification;
using Poco::Net::ServerSocket;
using Poco::Net::Socket;
using Poco::Net::SocketReactor;
using Poco::Net::StreamSocket;
using Poco::Observer;
using Poco::NObserver;
using Poco::AutoPtr;
using Poco::FastMutex;
using Poco::Thread;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
using Poco::Runnable;







class EchoServer: public Poco::Util::ServerApplication
{
public:
    EchoServer(): _helpRequested(false)
    {
    }
    
    ~EchoServer()
    {
    }

protected:
    void initialize(Application& self)
    {
        loadConfiguration(); // load default configuration files, if present
        ServerApplication::initialize(self);
    }
        
    void uninitialize()
    {
        ServerApplication::uninitialize();
    }

    void defineOptions(OptionSet& options)
    {
        ServerApplication::defineOptions(options);
        
        options.addOption(
            Option("help", "h", "display help information on command line arguments")
                .required(false)
                .repeatable(false));
    }

    void handleOption(const std::string& name, const std::string& value)
    {
        ServerApplication::handleOption(name, value);

        if (name == "help")
            _helpRequested = true;
    }

    void displayHelp()
    {
        HelpFormatter helpFormatter(options());
        helpFormatter.setCommand(commandName());
        helpFormatter.setUsage("OPTIONS");
        helpFormatter.setHeader("An echo server implemented using the Reactor and Acceptor patterns.");
        helpFormatter.format(std::cout);
    }

    int main(const std::vector<std::string>& args)
    {
        if (_helpRequested)
        {
            displayHelp();
        }
        else
        {
            // get parameters from configuration file
            unsigned short port = (unsigned short) config().getInt("EchoServer.port", 9977);
            
            // set-up a server socket
            //ServerSocket svs(port);
            // set-up a SocketReactor...
            //SocketReactor reactor;
            // ... and a SocketAcceptor
            //SocketAcceptor<EchoServiceHandler> acceptor(svs, reactor);
            // run the reactor in its own thread so that we can wait for 
            // a termination request 
            Iothread abc;
            Thread thread;
            thread.start(abc);
            // wait for CTRL-C or kill
            waitForTerminationRequest();
            // Stop the SocketReactor
            thread.join();
        }
        return Application::EXIT_OK;
    }
    
private:
    bool _helpRequested;
};




int main(int argc, char** argv)
{
    EchoServer app;
    return app.run(argc, argv);
}
